home *** CD-ROM | disk | FTP | other *** search
-
- { *********************************************************************** }
- { SDImage V1.03 }
- { as of 14 February 1989 }
- { }
- { SDImage V1.03 is a graphics image save/display utility which allows }
- { you to save graphic images to memory or disk and redisplay them. }
- { Image files can be read in another program or at a later date by }
- { referring to the file by it's reference number in DisplayImage. }
- { This unit is only dependant upon the BGI Graph unit. All activity is }
- { performed through the BGI, so anything that BGI supports SDImage also }
- { supports automatically. Image size is not a factor. SDImage }
- { automatically handles images that are larger than 64K. In fact, it }
- { can handle any size image without requiring massive heap storage. }
- { If the image size exceeds the buffer size, it will be automatically }
- { stored to a disk file. Thus a full VGA screen could be saved with }
- { a buffer size of only 1K. Note: It will take longer to save/display }
- { the image with smaller buffers since the image has to be stored and }
- { retrieved to disk. }
- { }
- { The mechanism that SDImage uses to save an image to disk is one }
- { file per image. Thus if you intend to save lots of images, I strongly }
- { recommend that you place them in a seperate subdirectory to help keep }
- { things uncluttered. Also be aware that SDImage will leave image files }
- { laying around if you don't remove them yourself. Which is another }
- { good reason for putting the image files in their own directory so }
- { that you can quickly find them and delete them if this is a problem. }
- { }
- { It should be further noted that to operate correctly, the image }
- { buffer size that is used to read in an image must be the same size }
- { (or larger) than the image buffer that was used to save the image. }
- { Because of this, if the image buffer size is too small, SDImage will }
- { automatically resize the image read buffer to the correct size. }
- { }
- { Version 1.03 adds the ability to do RLE (Run Length Encoding) on the }
- { image file to reduce the size of the image file saved to disk. }
- { Additionally version 1.03 corrects an obscure bug in 1.02 which caused }
- { images to occasionally be partially damaged in the Expand/Merge }
- { special effects modes. }
- { }
- { Originally written by Michael Day 12 November 1988 }
- { Copyright 1988 by Michael Day }
- { Version 1.01 released to the public domain on 19 November 1988 }
- { }
- { This version (V1.03) is released to the public domain }
- { as of 13 February 1989 }
- { *********************************************************************** }
- { history: }
- { V1.01 - 19 Nov 88 - first public domain release }
- { V1.02 - 25 Nov 88 - corrected bug in special effects }
- { V1.03 - 14 Feb 89 - added RLE compression, fixed minor SE bug }
-
- unit SDImage;
- interface
- uses graph;
-
- const
- ImageError : word = 0; {contains one of the possible errors below}
-
- NoImageError = 0; {Don't Worry, Be Happy! Everything's cool.}
- ImageDiskError = 1; {Either file not found or a bum disk}
- ImageBufNumTooBig = 2; {Too big a number, See MaxImageBuf const}
-
- {-------------------------------------------------------------------------}
- {Save a graphic screen Image, using Image reference number "Img" and}
- {working buffer "Buf". x1,y1,x2,y2 specify the screen area to save}
- {If something goes wrong, this function will return false.}
- {The lower four bits of "Style" controls the special effects.}
- {The upper four bits of Style controls the disk/buffer action.}
- {If bit 7 is on, then the image will always be forced to disk.}
- {If bit 7 is off, then the image will stay in the buffer if it can.}
- {If the image is bigger than the buffer then it is flushed to disk anyway.}
- {If bit 4 is on and the image is headed for the disk, then an RLE }
- {compression will be attempted no compression if result > non-compressed.}
- {Note: special effects only operate when the image is read from the disk.}
- {In fact it works because it uses the disk buffering as an inherent part}
- {of the effects control. EMS buffering is not currently implemented.}
- {0=Pull Down, 1=Pull Up, 2=Pull Right, 3=Pull Left, 4=Merge Vertical,}
- {5=Expand Vertical, 6=Merge Horizontal, 7=Expand Horizontal.}
-
- function SaveImage(Img,Buf:word; x1,y1,x2,y2:integer; Style:word):boolean;
-
- {-------------------------------------------------------------------------}
- {Displays a graphic screen image using image reference number Img and}
- {working buffer "Buf". If an image is residing in the buffer and is the}
- {correct image, then it will be displayed from the buffer. If the image}
- {is not the correct one, or there is no image currently saved in the}
- {buffer, then the buffer will be flushed to disk and the requested image}
- {will be read from the disk (if found) and displayed. If ImgClr is ture,}
- {then the image will be cleared from the buffer after being displayed.}
- {If the image came from disk, then the disk file will be erased as well.}
- {If ImgClr is false, then the image buffer and disk are left as they}
- {were found. If something goes wrong, this function will return false.}
-
- function DisplayImage(Img,Buf:word; ImgClr:boolean):boolean;
-
- {-------------------------------------------------------------------------}
- {The SaveImage function will automatically allocate an image buffer of the}
- {default size on the first use if none exists. If you wish to use a larger}
- {or smaller buffer, then you must use AllocImageBuf to allocate the desired}
- {image buffer size. If an image already exists in the buffer, it will be}
- {lost. Any existing old buffer space will be automatically released.}
- {If there is not enough heap space to allocate the buffer, this function}
- {will return a false condition.}
-
- function AllocImageBuf(Buf:word; Size:word):boolean;
-
- {-------------------------------------------------------------------------}
- {This releases the image buffer used with an image. You can call this to}
- {pick up heap space if you don't need the buffer anymore. As always,}
- {if the buffer is not allocated at the time SaveImage is called, then}
- {the default sized buffer will be allocated. Thus if you don't mind a}
- {slight slow down in the image process, you could call this after calling}
- {DisplayImage to keep heap usage to a minimum. Though keep in mind that}
- {if you release the buffer, any saved image in the buffer will be lost.}
-
- function ReleaseImageBuf(Buf:word):boolean;
-
- {-------------------------------------------------------------------------}
- {This sets a new path to be used for the image files. If the path does not}
- {exist, then it will be unchanged, and the function returns false.}
- {the Default path is to use the current default directory (i.e. no path).}
-
- function SetImagePath(Path:string):boolean;
-
- {-------------------------------------------------------------------------}
- {If an image is in the specified buffer, then the image will be flushed}
- {to disk. This can be used in preperation to releasing the buffer in order}
- {to gain more heap space. If the image could not be written to disk, then}
- {the function is aborted and returns false.}
-
- function FlushImage(Buf:word):boolean;
-
- {-------------------------------------------------------------------------}
- {An image can be deleted with this function. This will delete both images}
- {in the buffer and/or on disk. Retuns false if the image cannot be deleted}
-
- function DeleteImage(Img,Buf:word):boolean;
-
-
- { *********************************************************************** }
-
- implementation
-
- type
- string8 = string[8];
- string80 = string[80];
- ImgRect = record Xmin,Ymin,Xmax,Ymax:integer; end;
-
- {- this gets saved to disk at the beginning of the image file -}
- ImageDefRec = record {18 bytes}
- ImageNum : word; {image reference number in use}
- MaxImgSize : word; {size of buffer used to write the image}
- ImgArea : ImgRect; {the overall image area definition}
- ImgType : word; {how to save/display (special effects)}
- StepSize : word; {how many pixel rows per segment}
- StepCount : word; {how many image segments used}
- WrkSize : word; {how big full image is; $ffff= over 64K}
- end;
-
- {- this is put at the begining of packed records -}
- ImagePakRec = record
- PakSize : word; {how long this record is}
- PakStart : word; {where actual packing starts}
- end;
-
- {- this is only used by the image buffer -}
- ImageBufRec = record {16 bytes}
- MaxBufSize : word; {how big the image buffer is}
- RawImage : pointer; {points to image buffer on heap}
- RawArea : ImgRect; {image segment area}
- RawSize : word; {size of image segment; 0=empty buffer}
- end;
-
- const {variable constants}
- ImgFileError : boolean = false; {a disk error of some sort occured}
- ImgPath : string80 = ''; {Path used to get to the image files}
-
- const {fixed constants}
- MaxImageBuf = 20; {maximum allowed working buffers}
- MaxRawImage = 5000; {default image buffer size in bytes}
- ImgExpCount = 5; {Explode increment count}
- ImgName = 'SDI'; {Image file name (five digits are added)}
- ImgNameTag = '.IMG'; {Image file name tag (extent)}
- ImgFileWrite = true; {Open an image file for writing}
- ImgFileRead = false; {Open an image file for reading}
- ImgAreaWrite = true; {Write to the image file}
- ImgAreaRead = false; {Read from the image file}
-
- var {plain old variables}
- ImgBuf : array[0..MaxImageBuf] of ImageBufRec; {buffer info}
- ImgDef : array[0..MaxImageBuf] of ImageDefRec; {disk info}
- ImgFile : file;
-
- { ----------------------------------------------------------------------- }
- { ImgType }
- { +---+-----+---------+------+-------------+ +------+-------+-----+-----+ }
- { |bit| 3 | 2 | 1 | 0 | | 7 | 6 | 5 | 4 | }
- { +---+-----+---------+------+-------------+ +------+-------+-----+-----+ }
- { | 1 | --- | Xpd/Mrg | Horz | Xpd/Left/Dn | | Disk | EMS | --- | RLE | }
- { +---+-----+---------+------+-------------+ +------+-------+-----+-----+ }
- { | 0 | --- | Pull | Vert | Mrg/Rght/Up | | Auto | NoEMS | --- | BIN | }
- { +---+-----+---------+------+-------------+ +------+-------+-----+-----+ }
-
- {Note: EMS is not currently implemented }
-
- { *********************************************************************** }
- { misc support functions }
- { *********************************************************************** }
-
- {--------------------------------------------------}
- {convert a word to a zero filled string}
- function z5str(W:word):string8;
- var S:string8;
- begin
- str(W,S);
- while length(S) < 5 do S := '0'+S;
- z5str := S;
- end;
-
- {--------------------------------------------------}
- {check for invalid Buf # }
- function ImageCheckOK(Buf:word):boolean;
- begin
- if Buf > MaxImageBuf then
- begin
- ImageCheckOK := false;
- ImageError := ImageBufNumTooBig;
- Exit;
- end;
- ImageError := NoImageError;
- ImageCheckOK := true;
- end;
-
-
- { *********************************************************************** }
- { Internal disk functions }
- { *********************************************************************** }
-
- {$I-}
-
- {-------------------------------------------------------------------------}
- { OpenImageFile }
- {-------------------------------------------------------------------------}
- {open an image file for reading or writing }
- function OpenImageFile(Buf:word; ImgWrite:boolean):boolean;
- var RawCount:word;
- begin
- OpenImageFile := false;
- if IOResult = 0 then {nop} ;
- ImgFileError := true;
- Assign(ImgFile,ImgPath+ImgName+z5str(ImgDef[Buf].ImageNum)+ImgNameTag);
- if ImgWrite then
- begin
- ImgDef[Buf].MaxImgSize := ImgBuf[Buf].MaxBufSize;
- rewrite(ImgFile,1);
- BlockWrite(ImgFile, ImgDef[Buf], sizeof(ImgDef[Buf]), RawCount);
- if (IOResult <> 0) or (sizeof(ImgDef[Buf]) <> RawCount) then Exit;
- end
- else
- begin
- reset(ImgFile,1);
- BlockRead(ImgFile, ImgDef[Buf], sizeof(ImgDef[Buf]), RawCount);
- if (IOResult <> 0) or (sizeof(ImgDef[Buf]) <> RawCount) then Exit;
- if ImgDef[Buf].MaxImgSize > Imgbuf[Buf].MaxBufSize then
- begin
- if not AllocImageBuf(Buf,ImgDef[Buf].MaxImgSize) then Exit;
- end;
- end;
- ImgFileError := false;
- OpenImageFile := true;
- end;
-
- {-------------------------------------------------------------------------}
- { CloseImageFile }
- {-------------------------------------------------------------------------}
- {close the image file 'cause we're done with it}
- function CloseImageFile:boolean;
- begin
- CloseImageFile := false;
- Close(ImgFile);
- if (IOResult <> 0) then ImgFileError := true;
- if ImgFileError then
- begin
- ImageError := ImageDiskError;
- Exit;
- end;
- CloseImageFile := true;
- end;
-
-
- {-------------------------------------------------------------------------}
- { ScanImg }
- {-------------------------------------------------------------------------}
- function ScanImg(var RawImage; Size:word):word;
- Inline(
- {;function ScanImg(var RawImage:byte; Size:word):word;}
- {;this scans a buffer, and returns a pointer into the}
- {;buffer for where to start packing. A value equal to}
- {;the length of the buffer means that it cannot be packed.}
- {start:}
- $59 { pop cx ;get buffer length}
- /$89/$CB { mov bx,cx ;copy into bx too}
- /$5E { pop si ;get image pointer}
- /$89/$F7 { mov di,si ;put copy in di}
- /$58 { pop ax ;get image buffer seg}
- /$1E { push ds ;save current ds}
- /$55 { push bp ;and bp}
- /$89/$CD { mov bp,cx ;copy length to bp too}
- /$8E/$D8 { mov ds,ax ;point ds to buffer}
- /$09/$C9 { or cx,cx ;if zero length buffer}
- /$74/$54 { jz norle ;abort}
- /$31/$D2 { xor dx,dx ;clear sameness counter}
- /$8A/$04 { mov al,[si] ;get first byte}
- {scloop:}
- /$88/$C4 { mov ah,al ;save old value}
- /$42 { inc dx ;inc sameness count}
- /$49 { dec cx ;done yet?}
- /$74/$37 { jz scdone ;yes, so go pack it up}
- /$46 { inc si ;update read pointer}
- /$8A/$04 { mov al,[si] ;get new value}
- /$38/$C4 { cmp ah,al ;same as old value?}
- /$75/$06 { jnz ntsame ;no, so update}
- /$81/$FA/$FF/$00 { cmp dx,255 ;if dx = 255}
- /$75/$ED { jnz scloop ;force update anyway}
- {ntsame:}
- /$81/$FA/$03/$00 { cmp dx,3 ;if more than 3 the same}
- /$7F/$12 { jg dorle ;than pack it down}
- /$80/$FC/$00 { cmp ah,0 ;or if it was a 0}
- /$74/$0D { jz dorle ;do a pack anyway}
- /$29/$D3 { sub bx,dx ;adjust buffer length}
- /$72/$2E { jc norle ;abort if no room}
- /$31/$D2 { xor dx,dx ;clear counter}
- /$39/$FE { cmp si,di ;if si <> di}
- /$75/$D8 { jnz scloop ;then continue}
- /$47 { inc di ;else adjust di}
- /$EB/$D5 { jmp scloop ;and continue}
- {dorle:}
- /$81/$EB/$03/$00 { sub bx,3 ;adjust buffer length }
- /$72/$1F { jc norle ;abort if no room}
- /$39/$D9 { cmp cx,bx ;if buffer pointer below}
- /$7C/$04 { jl notrlex ;read pointer fix it up}
- /$89/$F7 { mov di,si ;by adjusting to current}
- /$89/$CB { mov bx,cx}
- {notrlex:}
- /$31/$D2 { xor dx,dx ;clear counter}
- /$EB/$C3 { jmp scloop ;loop until done}
- {scdone:}
- /$29/$D3 { sub bx,dx ;adjust for sameness}
- /$72/$0F { jc norle}
- /$81/$EB/$03/$00 { sub bx,3 ;need a little extra space}
- /$72/$09 { jc norle ;to do this stuff}
- /$29/$FE { sub si,di ;compute pack length}
- /$89/$E8 { mov ax,bp ;get old length}
- /$29/$F0 { sub ax,si ;compute pack start offset }
- /$E9/$02/$00 { jmp scexit ;return it to caller}
- {norle:}
- /$89/$E8 { mov ax,bp ;return buffer length}
- {scexit:}
- /$5D { pop bp}
- /$1F { pop ds}
- { end}
- );
-
- {-------------------------------------------------------------------------}
- { PakImg }
- {-------------------------------------------------------------------------}
- function PakImg(var RawImage; Size,Start:word):word;
- Inline(
- {;function PakImg(var RawImage; Size,Start:word):word;}
- {;this scans a buffer, and returns a pointer into the}
- {;buffer for where to start packing. A value equal to}
- {;the length of the buffer means that it cannot be packed.}
- {start:}
- $5B { pop bx ;get paking start offset}
- /$4B { dec bx ;adjust for offset}
- /$59 { pop cx ;get buffer length}
- /$89/$C8 { mov ax,cx ;temp save count}
- /$29/$D9 { sub cx,bx ;calc remainder count}
- /$5E { pop si ;get image pointer}
- /$01/$DE { add si,bx ;add start offset to it}
- /$89/$F7 { mov di,si ;put copy in di}
- /$5A { pop dx ;get image buffer seg}
- /$1E { push ds ;save current ds}
- /$8E/$DA { mov ds,dx ;point ds to buffer}
- /$09/$C0 { or ax,ax ;if zero length, abort}
- /$74/$52 { jz pkexit}
- /$39/$D8 { cmp ax,bx ;if start is at end, abort}
- /$74/$4E { jz pkexit}
- /$31/$D2 { xor dx,dx ;clear sameness counter}
- /$8A/$04 { mov al,[si] ;get first byte}
- {pkloop:}
- /$88/$C4 { mov ah,al ;save old value}
- /$42 { inc dx ;inc sameness count}
- /$49 { dec cx ;done yet?}
- /$74/$33 { jz pkdone ;yes, so go pack it up}
- /$46 { inc si ;update read pointer}
- /$8A/$04 { mov al,[si] ;get new value}
- /$38/$C4 { cmp ah,al ;same as old value?}
- /$75/$06 { jnz pkntsm ;no, so update}
- /$81/$FA/$FF/$00 { cmp dx,255 ;if dx = 255}
- /$75/$ED { jnz pkloop ;force update anyway}
- {pkntsm:}
- /$81/$FA/$03/$00 { cmp dx,3 ;if more than 3 the same}
- /$7F/$0F { jg pkrle ;than pack it down}
- /$80/$FC/$00 { cmp ah,0 ;or if it was a 0}
- /$74/$0A { jz pkrle ;do a pack anyway}
- /$01/$D3 { add bx,dx ;add to length count}
- {ntslp:}
- /$88/$25 { mov [di],ah ;copy bytes to buffer}
- /$47 { inc di ;inc copy pointer}
- /$4A { dec dx ;copy until done}
- /$75/$FA { jnz ntslp }
- /$EB/$D8 { jmp pkloop ;and continue}
- {pkrle:}
- /$81/$C3/$03/$00 { add bx,3 ;add to length count}
- /$88/$25 { mov [di],ah ;save image byte}
- /$47 { inc di}
- /$88/$15 { mov [di],dl ;save count}
- /$47 { inc di}
- /$31/$D2 { xor dx,dx ;clear counter}
- /$88/$35 { mov [di],dh ;0=packet}
- /$47 { inc di}
- /$EB/$C7 { jmp pkloop ;loop until done}
- {pkdone:}
- /$81/$C3/$03/$00 { add bx,3 ;add to length count}
- /$88/$25 { mov [di],ah ;save image byte}
- /$47 { inc di}
- /$88/$15 { mov [di],dl ;save count}
- /$47 { inc di}
- /$31/$D2 { xor dx,dx ;clear counter}
- /$88/$35 { mov [di],dh ;0=packet}
- /$47 { inc di}
- /$89/$D8 { mov ax,bx ;return count in ax}
- {pkexit:}
- /$1F { pop ds ;restore old ds}
- { end}
- );
-
-
- {-------------------------------------------------------------------------}
- { UnPakImage }
- {-------------------------------------------------------------------------}
- {unpacks an image inplace in the raw buffer}
- procedure UnPakImage(var RawImage; RawSize,PakSize,PakStart:word);
- Inline(
- {;on entry si points to the first entry to unpack}
- {;and di points to the end of the buffer. }
- {;es points to the buffer segment}
- {;procedure UnPakImage(var RawImage:byte; Rawsize,PakSize,PakStart:word);}
- {unrle:}
- $5B { pop bx ;get PakStart}
- /$5E { pop si ;get PakSize}
- /$5F { pop di ;get RawSize}
- /$58 { pop ax ;Get RawImage offset}
- /$01/$C3 { add bx,ax ;make stop pointer}
- /$4B { dec bx}
- /$01/$C6 { add si,ax ;make read pointer}
- /$4E { dec si}
- /$01/$C7 { add di,ax ;make write pointer}
- /$4F { dec di}
- /$58 { pop ax ;get RawImage segment}
- /$1E { push ds ;save current ds}
- /$8E/$D8 { mov ds,ax ;point to RawImage seg as ds}
- /$8A/$24 { mov ah,[si] ;get a value}
- /$4E { dec si}
- /$8A/$2C { mov ch,[si] ;get a value}
- /$4E { dec si}
- {unpklp:}
- /$39/$DF { cmp di,bx ;when the pointers are }
- /$7E/$27 { jle unpkdn ;the same (or less), we're done}
- /$88/$E0 { mov al,ah ;0=al,1=ah,2=ch}
- /$88/$EC { mov ah,ch}
- /$8A/$2C { mov ch,[si] ;get next value}
- /$4E { dec si}
- /$08/$C0 { or al,al ;is it a packet?}
- /$74/$05 { jz unpkit ;yes, so unpack it}
- /$88/$05 { mov [di],al ;otherwise just store it}
- /$4F { dec di}
- /$EB/$EC { jmp unpklp ;and continue}
- {unpkit:}
- /$88/$E1 { mov cl,ah ;get pack count}
- /$88/$E8 { mov al,ch ;get image byte}
- /$8A/$24 { mov ah,[si] ;update look ahead regs}
- /$4E { dec si}
- /$8A/$2C { mov ch,[si]}
- /$4E { dec si}
- {unpkrl:}
- /$39/$DF { cmp di,bx ;when the pointers are }
- /$7E/$09 { jle unpkdn ;the same (or less), we're done}
- /$88/$05 { mov [di],al ;and unpack the image}
- /$4F { dec di ;adjust pointer}
- /$FE/$C9 { dec cl}
- /$75/$F5 { jnz unpkrl}
- /$EB/$D5 { jmp unpklp ;go get next one}
- {unpkdn: ;that's it, we're done}
- /$1F { pop ds ;restore old ds}
- { end}
- );
-
-
- {-------------------------------------------------------------------------}
- { PackImgRW }
- {-------------------------------------------------------------------------}
- {reads or writes file to/from disk using rle packing if requested}
- procedure PackImgRW(Buf:word; ImgWrt:boolean);
- var RawCount:word;
- PakInfo:ImagePakRec;
- begin
- with ImgBuf[Buf],RawArea,PakInfo do
- begin
- RawSize := ImageSize(Xmin,Ymin,Xmax,Ymax);
- if ImgWrt then
- begin
- if ImgDef[Buf].ImgType and $10 = $10 then
- begin
- PakStart := ScanImg(RawImage^,RawSize);
- PakSize := PakImg(RawImage^,RawSize,PakStart);
- BlockWrite(ImgFile, PakInfo, sizeof(PakInfo), RawCount);
- BlockWrite(ImgFile, RawImage^, PakSize, RawCount);
- if RawCount = PakSize then RawCount := RawSize;
- end
- else
- begin
- BlockWrite(ImgFile, RawImage^, RawSize, RawCount);
- end;
- end
- else
- begin
- if ImgDef[Buf].ImgType and $10 = $10 then
- begin
- BlockRead(ImgFile, PakInfo, sizeof(PakInfo), RawCount);
- BlockRead(ImgFile, RawImage^, PakSize, RawCount);
- UnPakImage(RawImage^,RawSize,PakSize,PakStart);
- if RawCount = PakSize then RawCount := RawSize;
- end
- else
- begin
- BlockRead(ImgFile, RawImage^, RawSize, RawCount);
- end;
- end;
- if RawCount <> RawSize then ImgFileError := true;
- end;
- end;
-
- {-------------------------------------------------------------------------}
- { RWrawImage }
- {-------------------------------------------------------------------------}
- {read/write the image segment from/to disk }
- procedure RWrawImage(Buf:word; ImgWrt:boolean);
- var RawCount:word;
- begin
- with ImgBuf[Buf],RawArea do
- begin
- if ImgWrt then
- begin
- GetImage(Xmin,Ymin,Xmax,Ymax,RawImage^);
- PackImgRW(Buf,ImgWrt);
- end
- else
- begin
- PackImgRW(Buf,ImgWrt);
- if not ImgFileError then
- PutImage(Xmin,Ymin,RawImage^,NormalPut);
- end;
- RawSize := 0;
- end;
- end;
-
- {-------------------------------------------------------------------------}
- { RWImageArea }
- {-------------------------------------------------------------------------}
- procedure RWImageArea(Buf:byte; ImgWrt:boolean);
- var Area1,Area2:ImgRect;
- begin
- with ImgBuf[Buf],ImgDef[Buf],RawArea do
- begin
- RawArea := ImgArea;
- if WrkSize <= MaxBufSize then
- begin
- RWrawImage(Buf,ImgWrt);
- Exit;
- end;
-
- case (ImgType and $07) of
-
- $00 : {Pull Down (Vertical)}
- begin
- Ymax := Ymin + pred(StepSize);
- while Ymax < ImgArea.Ymax do
- begin
- RWrawImage(Buf,ImgWrt);
- Ymin := Ymin + StepSize;
- Ymax := Ymax + StepSize;
- end;
- Ymax := ImgArea.Ymax;
- RWrawImage(Buf,ImgWrt);
- end;
-
- $01 : {Pull Up (Vertical)}
- begin
- Ymin := Ymax - pred(StepSize);
- while Ymin > ImgArea.Ymin do
- begin
- RWrawImage(Buf,ImgWrt);
- Ymin := Ymin - StepSize;
- Ymax := Ymax - StepSize;
- end;
- Ymin := ImgArea.Ymin;
- RWrawImage(Buf,ImgWrt);
- end;
-
- $02 : {Pull Right (Horizontal)}
- begin
- Xmax := Xmin + pred(StepSize);
- while Xmax < ImgArea.Xmax do
- begin
- RWrawImage(Buf,ImgWrt);
- Xmin := Xmin + StepSize;
- Xmax := Xmax + StepSize;
- end;
- Xmax := ImgArea.Xmax;
- RWrawImage(Buf,ImgWrt);
- end;
-
- $03 : {Pull Left (Horizontal)}
- begin
- Xmin := Xmax - pred(StepSize);
- while Xmin > ImgArea.Xmin do
- begin
- RWrawImage(Buf,ImgWrt);
- Xmin := Xmin - StepSize;
- Xmax := Xmax - StepSize;
- end;
- Xmin := ImgArea.Xmin;
- RWrawImage(Buf,ImgWrt);
- end;
-
- $04 : {Mrg Vertical}
- begin
- begin
- Area1 := ImgArea;
- Area2 := ImgArea;
- Area1.Ymax := Area1.Ymin + pred(StepSize);
- Area2.Ymin := Area2.Ymax - pred(StepSize);
- while Area1.Ymax < Area2.Ymin do
- begin
- RawArea := Area1;
- RWrawImage(Buf,ImgWrt);
- Area1.Ymin := Area1.Ymin + StepSize;
- Area1.Ymax := Area1.Ymax + StepSize;
- RawArea := Area2;
- RWrawImage(Buf,ImgWrt);
- Area2.Ymin := Area2.Ymin - StepSize;
- Area2.Ymax := Area2.Ymax - StepSize;
- end;
- RawArea := Area1;
- while RawArea.Ymax < Area2.Ymax do
- begin
- RWrawImage(Buf,ImgWrt);
- Ymin := Ymin + StepSize;
- Ymax := Ymax + StepSize;
- end;
- if RawArea.Ymin <= Area2.Ymax then
- begin
- Ymax := Area2.Ymax;
- RWrawImage(Buf,ImgWrt);
- end;
- end;
- end;
-
- $05 : {Xpd Vertical}
- begin
- begin
- Area1 := ImgArea;
- Area2 := ImgArea;
- Area1.Ymax := ImgArea.Ymin+((ImgArea.Ymax-ImgArea.Ymin)shr 1);
- Area1.Ymin := Area1.Ymax - pred(StepSize);
- Area2.Ymin := succ(Area1.Ymax);
- Area2.Ymax := Area2.Ymin + pred(StepSize);
- while (Area1.Ymin>ImgArea.Ymin) and (Area2.Ymax<ImgArea.Ymax) do
- begin
- if (Area1.Ymin > ImgArea.Ymin) then
- begin
- RawArea := Area1;
- RWrawImage(Buf,ImgWrt);
- Area1.Ymin := Area1.Ymin - StepSize;
- Area1.Ymax := Area1.Ymax - StepSize;
- end;
- if (Area2.Ymax < ImgArea.Ymax) then
- begin
- RawArea := Area2;
- RWrawImage(Buf,ImgWrt);
- Area2.Ymin := Area2.Ymin + StepSize;
- Area2.Ymax := Area2.Ymax + StepSize;
- end;
- end;
- RawArea := Area1;
- if (RawArea.Ymax >= ImgArea.Ymin) then
- begin
- RawArea.Ymin := ImgArea.Ymin;
- RWrawImage(Buf,ImgWrt);
- end;
- RawArea := Area2;
- if (RawArea.Ymin <= ImgArea.Ymax) then
- begin
- RawArea.Ymax := ImgArea.Ymax;
- RWrawImage(Buf,ImgWrt);
- end;
- end;
- end;
-
- $06 : {Mrg Horizontal}
- begin
- begin
- Area1 := ImgArea;
- Area2 := ImgArea;
- Area1.Xmax := Area1.Xmin + pred(StepSize);
- Area2.Xmin := Area2.Xmax - pred(StepSize);
- while Area1.Xmax < Area2.Xmin do
- begin
- RawArea := Area1;
- RWrawImage(Buf,ImgWrt);
- Area1.Xmin := Area1.Xmin + StepSize;
- Area1.Xmax := Area1.Xmax + StepSize;
- RawArea := Area2;
- RWrawImage(Buf,ImgWrt);
- Area2.Xmin := Area2.Xmin - StepSize;
- Area2.Xmax := Area2.Xmax - StepSize;
- end;
- RawArea := Area1;
- while RawArea.Xmax < Area2.Xmax do
- begin
- RWrawImage(Buf,ImgWrt);
- Xmin := Xmin + StepSize;
- Xmax := Xmax + StepSize;
- end;
- if RawArea.Xmin <= Area2.Xmax then
- begin
- Xmax := Area2.Xmax;
- RWrawImage(Buf,ImgWrt);
- end;
- end;
- end;
-
- $07 : {Xpd Horizontal}
- begin
- begin
- Area1 := ImgArea;
- Area2 := ImgArea;
- Area1.Xmax := ImgArea.Xmin+((ImgArea.Xmax-ImgArea.Xmin)shr 1);
- Area1.Xmin := Area1.Xmax - pred(StepSize);
- Area2.Xmin := succ(Area1.Xmax);
- Area2.Xmax := Area2.Xmin + pred(StepSize);
- while (Area1.Xmin > ImgArea.Xmin) and (Area2.Xmax < ImgArea.Xmax) do
- begin
- if (Area1.Xmin > ImgArea.Xmin) then
- begin
- RawArea := Area1;
- RWrawImage(Buf,ImgWrt);
- Area1.Xmin := Area1.Xmin - StepSize;
- Area1.Xmax := Area1.Xmax - StepSize;
- end;
- if (Area2.Xmax < ImgArea.Xmax) then
- begin
- RawArea := Area2;
- RWrawImage(Buf,ImgWrt);
- Area2.Xmin := Area2.Xmin + StepSize;
- Area2.Xmax := Area2.Xmax + StepSize;
- end;
- end;
- RawArea := Area1;
- if (RawArea.Xmax >= ImgArea.Xmin) then
- begin
- RawArea.Xmin := ImgArea.Xmin;
- RWrawImage(Buf,ImgWrt);
- end;
- RawArea := Area2;
- if (RawArea.Xmin <= ImgArea.Xmax) then
- begin
- RawArea.Xmax := ImgArea.Xmax;
- RWrawImage(Buf,ImgWrt);
- end;
- end;
- end;
-
-
- end; {case}
- end; {with}
- end;
-
- {-------------------------------------------------------------------------}
- { WriteImage }
- {-------------------------------------------------------------------------}
- {write an image to buffer/disk }
- function WriteImage(Buf:word):boolean;
- var Iss,Ssc:word;
- begin
- WriteImage := false;
- with ImgBuf[Buf],ImgDef[Buf] do
- begin
- with ImgArea do
- begin
- if ImgType and $02 = $00 then {- $00=vertical action, $02=horizontal -}
- begin
- Ssc := Ymax-Ymin; {total image rows used}
- Iss := ImageSize(Xmin,Ymin,Xmax,succ(Ymin)); {image row size (bytes)}
- end
- else {Ssc= total row count}
- begin {Iss= row size in bytes}
- Ssc := Xmax-Xmin;
- Iss := ImageSize(Xmin,Ymin,succ(Xmin),Ymax);
- end;
- if MaxBufSize < Iss then {gotta have at least one rows}
- if not AllocImageBuf(Buf,Iss) then Exit; {worth of buffer space}
- StepSize := MaxBufSize div Iss;
- StepCount := Ssc div StepSize;
- if Ssc mod StepSize > 0 then inc(StepCount);
- end;
-
- if OpenImageFile(Buf,ImgFileWrite) then
- RWImageArea(Buf,ImgAreaWrite);
-
- if not CloseImageFile then
- begin
- Erase(ImgFile);
- RawSize := 0;
- if IOResult <> 0 then {nop} ;
- Exit;
- end;
- end;
- WriteImage := true;
- end;
-
-
- {-------------------------------------------------------------------------}
- { ReadImage }
- {-------------------------------------------------------------------------}
- {Read an image from the disk}
- function ReadImage(Buf:word; ImgClr:boolean):boolean;
- begin
- ReadImage := false;
- with ImgBuf[Buf],ImgDef[Buf] do
- begin
- if OpenImageFile(Buf,ImgFileRead) then
- RWImageArea(Buf,ImgAreaRead);
-
- if not CloseImageFile then Exit;
- if ImgClr then Erase(ImgFile);
- if IOResult <> 0 then Exit;
- end;
- ReadImage := true;
- end;
-
- {$I+}
-
-
- { *********************************************************************** }
- { External access functions }
- { *********************************************************************** }
-
- {-------------------------------------------------------------------------}
- { AllocImageBuf }
- {-------------------------------------------------------------------------}
- {This allocates a buffer for use with an image. You must call this before}
- {you can use an image buffer if you want it to be a different size than}
- {the default. If the buffer is not allocated at the time SaveImage is}
- {called, then the default sized buffer will be allocated.}
-
- function AllocImageBuf(Buf:word; Size:word):boolean;
- begin
- AllocImageBuf := false;
- if not ImageCheckOK(Buf) then Exit;
- with ImgBuf[Buf] do
- begin
- if RawImage <> nil then
- freemem(RawImage,MaxBufSize);
- RawSize := 0;
- MaxBufSize := 0;
- If MaxAvail < Size then Exit;
- GetMem(RawImage,Size);
- MaxBufSize := Size;
- ImgDef[Buf].MaxImgSize := Size;
- end;
- AllocImageBuf := true;
- end;
-
-
- {-------------------------------------------------------------------------}
- { ReleaseImageBuf }
- {-------------------------------------------------------------------------}
- {This releases the image buffer used with an image. You can call this to}
- {pick up heap space if you don't need the buffer anymore. As always,}
- {if the buffer is not allocated at the time SaveImage is called, then}
- {the default sized buffer will be allocated. Thus if you don't mind a}
- {slight slow down in the image process, you could call this after calling}
- {DisplayImage to keep heap usage to a minimum.}
-
- function ReleaseImageBuf(Buf:word):boolean;
- begin
- ReleaseImageBuf := false;
- if not ImageCheckOK(Buf) then Exit;
- with ImgBuf[Buf] do
- begin
- if RawImage <> nil then
- freemem(RawImage,MaxBufSize);
- RawImage := nil;
- RawSize := 0;
- MaxBufSize := 0;
- end;
- ReleaseImageBuf := true;
- end;
-
-
- {-------------------------------------------------------------------------}
- { SetImagePath }
- {-------------------------------------------------------------------------}
- {This sets a new path to be used for the image files. If the path does not}
- {exist, then it will be created. If an error occurs the function returns }
- {a false condition. The Default path is to use the current default directory}
- {(i.e. no path).}
-
- {$I-}
-
- function SetImagePath(Path:string):boolean;
- var TPath:string;
- begin
- SetImagePath := false;
- GetDir(0,TPath);
- ChDir(Path);
- if IOResult <> 0 then MkDir(Path);
- ChDir(TPath);
- if IOResult = 0 then ImgPath := Path+'\';
- if IOResult <> 0 then Exit;
- SetImagePath := true;
- end;
-
- {$I+}
-
- {-------------------------------------------------------------------------}
- { FlushImage }
- {-------------------------------------------------------------------------}
- {if there is an image in the buffer, flush it to disk}
-
- function FlushImage(Buf:word):boolean;
- var RawCount : word;
- begin
- FlushImage := false;
- if not ImageCheckOK(Buf) then Exit;
- with ImgBuf[Buf] do
- begin
- if RawSize > 0 then
- begin
- if OpenImageFile(Buf,ImgFileWrite) then
- PackImgRW(Buf,ImgFileWrite);
- RawSize := 0;
- if not CloseImageFile then Exit;
- end;
- end;
- FlushImage := true;
- end;
-
-
- {-------------------------------------------------------------------------}
- { DeleteImage }
- {-------------------------------------------------------------------------}
- {This deletes images in the buffer and on disk. Any image that might}
- {be in the buffer is lost. Any image disk file that exists by the given}
- {number will be deleted. If an error occurs during the delete, such }
- {as the requested image is not found, the function will return false.}
-
- {$I-}
-
- function DeleteImage(Img,Buf:word):boolean;
- var RawCount : word;
- begin
- DeleteImage := false;
- if not ImageCheckOK(Buf) then Exit;
- with ImgBuf[Buf] do
- begin
- RawSize := 0;
- if OpenImageFile(Buf,ImgFileWrite) then {nop} ;
- if CloseImageFile then Erase(ImgFile);
- RawSize := 0;
- if ImgFileError or (IOResult <> 0) then Exit;
- end;
- DeleteImage := true;
- end;
-
- {$I+}
-
- {-------------------------------------------------------------------------}
- { SaveImage }
- {-------------------------------------------------------------------------}
- { Saves the screen image under the box. This can be called to save the}
- { screen image before writing the box to the screen. Use DisplayImage to}
- { restore the image. The lower four bits of "Style" controls the special}
- { effects. The upper four bits of Style controls the disk/buffer action.}
- { If bit 7 is on, then the image will always be forced to disk.}
- { If bit 7 is off, then the image will stay in the buffer if it can.}
- { If the image is bigger than the buffer then it is flushed to disk anyway.}
- { If bit 4 is on and the image is headed for the disk, then an RLE }
- { compression will be attempted no compression if result > non-compressed.}
- { Note: special effects only operate when the image is read from the disk.}
- { In fact it works because it uses the disk buffering as an inherent part}
- { of the effects control. EMS buffering is not currently implemented.}
- { 0=Pull Down, 1=Pull Up, 2=Pull Right, 3=Pull Left, 4=Merge Vertical,}
- { 5=Expand Vertical, 6=Merge Horizontal, 7=Expand Horizontal.}
-
- function SaveImage(Img,Buf:word; x1,y1,x2,y2:integer; Style:word):boolean;
- begin
- SaveImage := false;
- if not ImageCheckOK(Buf) then Exit;
- if not FlushImage(Buf) then Exit; {flush image buffer}
- if ImgBuf[Buf].RawImage = nil then
- if not AllocImageBuf(Buf,MaxRawImage) then Exit;
-
- with ImgDef[Buf],ImgArea do
- begin
- ImageNum := Img;
- ImgType := Style;
- Xmin := x1;
- Ymin := y1;
- Xmax := x2;
- Ymax := y2;
- ImgBuf[Buf].RawArea := ImgArea;
- StepSize := Ymax-Ymin;
- StepCount := 1;
- WrkSize := ImageSize(Xmin,Ymin,Xmax,Ymax);
- if WrkSize = 0 then WrkSize := $ffff;
-
- if (ImgType and $80 = 0) and (WrkSize < ImgBuf[Buf].MaxBufSize) then
- begin {- save image to heap buffer -}
- ImgBuf[Buf].RawSize := WrkSize;
- GetImage(Xmin,Ymin,Xmax,Ymax,ImgBuf[Buf].RawImage^);
- end
- else
- begin {- write the image to disk -}
- if not WriteImage(Buf) then Exit;
- end;
- end;
- SaveImage := true;
- end;
-
- {-------------------------------------------------------------------------}
- { DisplayImage }
- {-------------------------------------------------------------------------}
- { Restores a previously saved box screen image. See SaveImage. }
- { If the desired image is in the buffer, then it comes from there.}
- { Otherwise the disk is searched for the desired image.}
- { If ImgClr is true, then the image buffer/file will be erased after}
- { the image has been displayed.}
-
- function DisplayImage(Img,Buf:word; ImgClr:boolean):boolean;
- begin
- DisplayImage := false;
- if not ImageCheckOK(Buf) then Exit;
-
- with ImgBuf[Buf] do
- begin
- if (Img = ImgDef[Buf].ImageNum) and (RawSize <> 0) then
- begin
- PutImage(RawArea.Xmin,RawArea.Ymin,RawImage^,NormalPut);
- if ImgClr then RawSize := 0;
- end
- else
- begin
- if not FlushImage(Buf) then Exit; {flush image buffer if not same}
- ImgDef[Buf].ImageNum := Img;
- if not ReadImage(Buf,ImgClr) then Exit; {read the requested image}
- end;
- end;
- DisplayImage := true;
- end;
-
-
- { *********************************************************************** }
- { initialization }
- begin
- fillchar(ImgBuf,sizeof(ImgBuf),0);
- fillchar(ImgDef,sizeof(ImgDef),0);
- end.
-